package com.luom.fsp.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.luom.fsp.common.ErrorCode;
import com.luom.fsp.constant.CommonConstant;
import com.luom.fsp.constant.RedisConstant;
import com.luom.fsp.exception.ThrowUtils;
import com.luom.fsp.mapper.ProductMapper;
import com.luom.fsp.model.dto.product.ProductQueryRequest;
import com.luom.fsp.model.dto.product.ProductUpdateRequest;
import com.luom.fsp.model.entity.Product;
import com.luom.fsp.model.entity.ProductSKU;
import com.luom.fsp.model.entity.User;
import com.luom.fsp.model.enums.ProductStatusEnum;
import com.luom.fsp.model.vo.ProductSKUVO;
import com.luom.fsp.model.vo.ProductVO;
import com.luom.fsp.service.ProductSKUService;
import com.luom.fsp.service.ProductService;
import com.luom.fsp.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品服务实现
 */
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Resource
    private ProductSKUService productSKUService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ProductMapper productMapper;

    /**
     * 校验数据
     *
     * @param product
     * @param add     对创建的数据进行校验
     */
    @Override
    public void validProduct(Product product, boolean add) {
        ThrowUtils.throwIf(product == null, ErrorCode.PARAMS_ERROR);

        Long id = product.getId();
        String name = product.getName();
        Long categoryId = product.getCategoryId();
        String description = product.getDescription();
        String status = product.getStatus();
        // 创建数据时，参数不能为空
        if (add) {
            ThrowUtils.throwIf(StringUtils.isBlank(name), ErrorCode.PARAMS_ERROR);
            ThrowUtils.throwIf(categoryId == null, ErrorCode.PARAMS_ERROR);
            Product one = getOne(new QueryWrapper<Product>().eq("name", name));
            ThrowUtils.throwIf(one != null, ErrorCode.PARAMS_ERROR, "商品名称已存在");
        }
        // 修改数据时，有参数则校验
        if (ObjectUtils.isNotEmpty(id)) {
            ThrowUtils.throwIf(id < 0, ErrorCode.PARAMS_ERROR);
        }
        if (StringUtils.isNotBlank(name)) {
            ThrowUtils.throwIf(name.length() > 20, ErrorCode.PARAMS_ERROR, "商品名称过长");
            ThrowUtils.throwIf(RegexUtils.isName(name), ErrorCode.PARAMS_ERROR, "商品名称含有非法字符");
        }
        if (ObjectUtils.isNotEmpty(categoryId)) {
            ThrowUtils.throwIf(categoryId < 0, ErrorCode.PARAMS_ERROR);
        }
        if (StringUtils.isNotBlank(description)) {
            ThrowUtils.throwIf(description.length() > 512, ErrorCode.PARAMS_ERROR, "商品描述过长");
        }
        if (StringUtils.isNotBlank(status)) {
            ThrowUtils.throwIf(!ProductStatusEnum.getValues().contains(status), ErrorCode.PARAMS_ERROR, "商品状态错误");
        }
    }

    /**
     * 获取查询条件
     *
     * @return
     */
    @Override
    public QueryWrapper<Product> getQueryWrapper(ProductQueryRequest request,boolean isSales) {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        if (request == null) {
            return queryWrapper;
        }

        Long id = request.getId();
        String name = request.getName();
        Long categoryId = request.getCategoryId();
        String description = request.getDescription();
        String status = request.getStatus();
        Date createTime = request.getCreateTime();
        String sortField = request.getSortField();
        String sortOrder = request.getSortOrder();
        // 模糊查询
        queryWrapper.like(StringUtils.isNotBlank(name), "name", name);
        queryWrapper.like(StringUtils.isNotBlank(description), "description", description);
        // 精确查询
        queryWrapper.eq(ObjectUtils.isNotEmpty(categoryId), "categoryId", categoryId);
        queryWrapper.eq(StringUtils.isNotBlank(status), "status", status);
        queryWrapper.ge(ObjectUtils.isNotEmpty(createTime), "createTime", createTime);
        if (!isSales){
            queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
            // 排序规则
            if (StringUtils.isNotBlank(sortField) && StringUtils.isNotBlank(sortOrder)) {
                boolean isAsc = sortOrder.equalsIgnoreCase(CommonConstant.SORT_ORDER_ASC);
                queryWrapper.orderBy(true, isAsc, sortField);
            }
        }else {
            int page = request.getCurrent();
            int size = request.getPageSize();
            long start = (page - 1) * size;
            long end = page * size - 1;

            // 2. 从 Redis 获取分页后的商品ID（根据排序方向）
            Set<String> productIds;
            if ("desc".equalsIgnoreCase(request.getSortOrder())) {
                productIds = stringRedisTemplate.opsForZSet().reverseRange(
                        RedisConstant.PRODUCT_SALES_STATISTIC_KEY, start, end
                );
            } else {
                productIds = stringRedisTemplate.opsForZSet().range(
                        RedisConstant.PRODUCT_SALES_STATISTIC_KEY, start, end
                );
            }

            // 3. 如果没有数据，直接返回空条件（避免全表扫描）
            if (CollUtil.isEmpty(productIds)) {
                queryWrapper.apply("1 = 0"); // 强制返回空结果
                return queryWrapper;
            }

            // 4. 保持 Redis 返回的 ID 顺序
            List<String> idList = new ArrayList<>(productIds);
            queryWrapper.in("id", idList)
                    .last("ORDER BY FIELD(id, " + String.join(",", idList) + ")");
        }
        return queryWrapper;

    }



    /**
     * 获取商品封装
     *
     * @param product
     * @return
     */
    @Override
    public ProductVO getProductVO(Product product, boolean isAdmin) {
        ProductVO productVO = ProductVO.objToVo(product);
        Long productId = product.getId();
        List<ProductSKUVO> productSKUVOList;
        if (isAdmin){

        productSKUVOList = productSKUService.list(new QueryWrapper<ProductSKU>()
                        .eq("productId", productId)).stream()
                .map(ProductSKUVO::objToVo)
                .collect(Collectors.toList());
        }else {
            productSKUVOList = productSKUService.list(new QueryWrapper<ProductSKU>()
                            .eq("productId", productId)
                            .eq("status", ProductStatusEnum.ACTIVE.getValue())).stream()
                    .map(ProductSKUVO::objToVo)
                    .collect(Collectors.toList());
        }
        productVO.setProductSKUVOList(productSKUVOList);
        productVO.setMinPrice(productSKUVOList.stream().map(ProductSKUVO::getPrice).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO));
        // 填充销量
        ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();
        String productIdKey = String.valueOf(productId);
        Double score = zSetOperations.score(RedisConstant.PRODUCT_SALES_STATISTIC_KEY, productIdKey);
        productVO.setSales(score != null ? score.intValue() : 0);
        return productVO;
    }

    /**
     * 分页获取商品封装
     *
     * @param productPage
     * @return
     */
    @Override
    public Page<ProductVO> getProductVOPage(Page<Product> productPage) {
        List<Product> productList = productPage.getRecords();
        Page<ProductVO> productVOPage = new Page<>(productPage.getCurrent(), productPage.getSize(), productPage.getTotal());

        if (CollUtil.isEmpty(productList)) {
            return productVOPage;
        }

        // 对象列表 => 封装对象列表
        List<ProductVO> productVOList = productList.stream()
                .map(ProductVO::objToVo)
                .collect(Collectors.toList());

        // 获取所有商品的ID
        List<Long> productIds = productList.stream()
                .map(Product::getId)
                .collect(Collectors.toList());
        // 批量查询商品规格表
        Map<Long, BigDecimal> productMinPriceMap = productSKUService.list(new QueryWrapper<ProductSKU>().in("productId", productIds))
                .stream()
                .collect(Collectors.groupingBy(
                        ProductSKU::getProductId, // 按商品ID分组
                        Collectors.collectingAndThen(
                                Collectors.minBy(Comparator.comparing(ProductSKU::getPrice)), // 获取每组的最小价格
                                opt -> opt.map(ProductSKU::getPrice).orElse(BigDecimal.ZERO) // 如果存在，则返回价格，否则返回默认值 BigDecimal.ZERO
                        )
                ));

        // 填充最小价格信息
        productVOList.forEach(productVO -> {
            BigDecimal minPrice = productMinPriceMap.getOrDefault(productVO.getId(), BigDecimal.ZERO);
            productVO.setMinPrice(minPrice);
            // 填充销量
            Double totalSales = stringRedisTemplate.opsForZSet().score(RedisConstant.PRODUCT_SALES_STATISTIC_KEY, productVO.getId().toString());
            productVO.setSales(totalSales != null ? totalSales.intValue() : 0);
        });


        /*// 批量查询商品规格表
        Map<Long, List<ProductSKUVO>> productSKUMap = productSKUService.list(new QueryWrapper<ProductSKU>().in("productId", productIds))
                .stream()
                .map(ProductSKUVO::objToVo)
                .collect(Collectors.groupingBy(ProductSKUVO::getProductId));

        // 填充信息
        productVOList.forEach(productVO -> {
            List<ProductSKUVO> productSKUVOList = productSKUMap.getOrDefault(productVO.getId(), Collections.emptyList());
            productVO.setProductSKUVOList(productSKUVOList);
        });*/

        productVOPage.setRecords(productVOList);
        return productVOPage;
    }

    @Override
    public boolean updateProduct(ProductUpdateRequest productUpdateRequest) {
        Product product = new Product();
        BeanUtils.copyProperties(productUpdateRequest, product);
        // 数据校验
        validProduct(product, false);
        // 判断是否存在
        long id = productUpdateRequest.getId();
        Product oldProduct = getById(id);
        ThrowUtils.throwIf(oldProduct == null, ErrorCode.NOT_FOUND_ERROR);
        // 如果是上架商品，判断能否上架
        if (ProductStatusEnum.ACTIVE.getValue().equals(productUpdateRequest.getStatus())) {
            QueryWrapper<ProductSKU> skuQueryWrapper = new QueryWrapper<>();
            skuQueryWrapper.eq("productId", oldProduct.getId());
            List<ProductSKU> list = productSKUService.list(skuQueryWrapper);
            ThrowUtils.throwIf(list.isEmpty(), ErrorCode.OPERATION_ERROR, "无商品规格，无法上架");
        }
        // 操作数据库
        boolean result = updateById(product);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return true;
    }

}
